﻿#include "Logic.h"
#include "MyPublicMacro.h"

#include "GnsClientFrame.h"
#include "IEventBridge.h"

#include "MsgCmd.h"
#include "MsgStruct.h"

CLogic*  CLogic::_pLauncher = nullptr;

CLogic::CLogic()
{
}

CLogic::~CLogic()
{
}

CLogic* CLogic::getInstance()
{
	if (_pLauncher == nullptr)
	{
		_pLauncher = CLogic::create();
		assert(_pLauncher);
	}

	return _pLauncher;
}

CLogic* CLogic::create()
{
	CLogic *_pLauncher = new(std::nothrow) CLogic();
	if (_pLauncher && _pLauncher->init())
	{
		//int iCount = _pLauncher->getReferenceCount();  // 获取当前的引用计数
		//////_pLauncher->autorelease();	// 将对象交给自动释放池
		//_pLauncher->retain();				// 很重要，可以让引用记数器加 1

		return _pLauncher;
	}
	else
	{
		delete _pLauncher;
		_pLauncher = nullptr;
		return nullptr;
	}
}

void CLogic::destoryInstance()
{
	if (_pLauncher != nullptr)
	{
		delete _pLauncher;
		_pLauncher = nullptr;
	}
}

bool CLogic::init()
{

	return true;
}

/* --------------------------------------------------------------------------
函数说明：连接结果的回调
传入参数：
iClientId			客户端 Socket 的 Id
bConnect		true 表示连接成功，false 表示连接失败
strErr				错误提示
返回值：
成功则返回 0，失败返回错误码
-------------------------------------------------------------------------- */
void CLogic::OnConnect(int iClientId, bool bConnect, int iReconnectCount, std::string  strErr)
{
	IEventBridge::EVENT_INFO eventInfo;
	eventInfo.iMainCode = CLIENT_INNER_CONNECT;
	eventInfo.copyToBody((char*)(&iReconnectCount), sizeof(iReconnectCount));

	if (bConnect)
	{
		//log("connect  %d success!", iClientId);

		// 视图模块要作的动作：结束转圈
		eventInfo.iSubCode = CC_SUCC_NO_CIRCLE;  // 连接成功，结束转圈
	}
	else
	{
		//log("connect  %d fail!", iClientId);

		// 获得当前重连次数
		int  iCurRetryCount = GnsClientFrame::getInstance()->getParamByType(iClientId, CPT_curRetryCount);

		if (iCurRetryCount < _startCircleCountConnect)  // 视图模块要作的动作：不转圈，给客户端一些连接的机会，体验感会好一些
		{
			eventInfo.iSubCode = CC_START_NO_CIRCLE;	// 在 开始转圈的连接次数 以内，不转圈
		}
		else if (iCurRetryCount < _endCircleCountConnect)  // 视图模块要作的动作：转圈【正在连接】
		{
			eventInfo.iSubCode = CC_CONNECT_CIRCLE_ING;		// 在  >开始转圈的连接次数 并且  <=结束转圈的连接次数 范围，开始转圈【正在连接】
		}
		else  // 视图模块要作的动作：结束转圈，并弹出【连接失败】的提示框
		{
			GnsClientFrame::getInstance()->closeSocket(iClientId);
			eventInfo.iSubCode = CC_FAIL_NO_CIRCLE;	// 结束转圈，并弹出【连接失败】的提示框
		}
	}

	IEventBridge::getInstance()->pushBack(eventInfo);
}

/* --------------------------------------------------------------------------
函数说明：断线重连的回调
传入参数：
iClientId						客户端 Socket 的 Id
bConnect					true 表示连接成功，false 表示连接失败
iReconnectCount		重连的次数
strErr							错误提示
返回值：
成功则返回 0，失败返回错误码
-------------------------------------------------------------------------- */
void CLogic::OnReconnectAfterOffline(int iClientId, bool bConnect, int iReconnectCount, std::string  strErr)
{
	IEventBridge::EVENT_INFO eventInfo;
	eventInfo.iClientId = iClientId;
	eventInfo.iMainCode = CLIENT_INNER_RE_CONNECT;
	eventInfo.copyToBody((char*)(&iReconnectCount), sizeof(iReconnectCount));

	if (bConnect)
	{
		//log("Reconnect  %d success!  No.%d ", iClientId, iReconnectCount);

		// 视图模块要作的动作：结束转圈
		eventInfo.iSubCode = RECC_SUCC_NO_CIRCLE;  // 连接成功，结束转圈
	}
	else
	{
		//log("Reconnect  %d fail!  No.%d ", iClientId, iReconnectCount);

		// 获得当前重连次数
		int  iCurRetryCount = GnsClientFrame::getInstance()->getParamByType(iClientId, CPT_curRetryCount);

		if (iCurRetryCount < _startCircleCountReconnectAfterOffline)  // 视图模块要作的动作：不转圈，给客户端一些连接的机会，体验感会好一些
		{
			eventInfo.iSubCode = RECC_START_NO_CIRCLE;	// 在 开始转圈的连接次数 以内，不转圈
		}
		else if (iCurRetryCount < _endCircleCountReconnectAfterOffline)  // 视图模块要作的动作：转圈【正在连接】
		{
			eventInfo.iSubCode = RECC_CONNECT_CIRCLE_ING;		// 在  >开始转圈的连接次数 并且  <=结束转圈的连接次数 范围，开始转圈【正在连接】
		}
		else  // 视图模块要作的动作：结束转圈，并弹出【连接失败】的提示框
		{
			GnsClientFrame::getInstance()->closeSocket(iClientId);
			eventInfo.iSubCode = RECC_FAIL_NO_CIRCLE;	// 结束转圈，并弹出【连接失败】的提示框
		}
	}

	IEventBridge::getInstance()->pushBack(eventInfo);
}

/* --------------------------------------------------------------------------
函数说明：断线的回调
传入参数：
	iClientId		客户端 Socket 的 Id
-------------------------------------------------------------------------- */
void CLogic::OnClose(int iClientId)
{
	log("socket %d  close !", iClientId);

	IEventBridge::EVENT_INFO eventInfo;
	eventInfo.iMainCode = MAIN_MSG_LOGIN;
	eventInfo.iSubCode = INNER_MSG_CLOSE_SOCKET;
}

/* --------------------------------------------------------------------------
函数说明：处理逻辑消息
传入参数：
	iMainCode			主码
	iSubCode			辅助码
	pData					要发送的数据
	iDataLen				要发送的数据长度
返回值：
	成功则返回 0，失败返回错误码
--------------------------------------------------------------------------*/
int CLogic::OnLogicMsg(int	iClientId, int iMainCode, int iSubCode, const char* pBody, int iBodyLen)
{
	GnsClientFrame* pGnsClientFrame = GnsClientFrame::getInstance();
	assert(pGnsClientFrame);

	IDataRepository*		pDataRepository = pGnsClientFrame->_pDataRepository;

	IEventBridge::EVENT_INFO eventInfo;
	eventInfo.iMainCode = iMainCode;
	eventInfo.iSubCode = iSubCode;
	int iRes = eventInfo.copyToBody(pBody, iBodyLen);
	assert(0 == iRes);
	if (0 == iRes)
	{
		IEventBridge::getInstance()->pushBack(eventInfo);
	}

	return 0;
}
